import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TestingSystem 

{
	private static String hwloc_info;
	private static String lstopo_physical;
	private static String numactl_hardware;

	private static int NuNumas;
	private static int NuSockets;
	private static int NuCores;
	private static int NuPUs;
	
	private static String MachineID;
	private static String KernelVersion;
	private static String RHVersion;

	
public TestingSystem()
{	getHwloc_info();
	getLstopo_physical();
	getNumactl_hardware();
	GetCPUConfiguration();
	GetRHELVersion();	}

public static String getMachineID() 
{	return MachineID;	}

public static void setMachineID(String machineID) 
{	MachineID = machineID;	}

public static String getKernelVersion() 
{	return KernelVersion;	}

public static void setKernelVersion(String kernelVersion) 
{	KernelVersion = kernelVersion;	}

public static String getRHVersion() 
{	return RHVersion;	}

public static void setRHVersion(String rHVersion) 
{	RHVersion = rHVersion;	}

public int getNuNumas() 
{	return NuNumas;		}

private static void setNuNumas(int nuNumas) 
{	NuNumas = nuNumas;	}

public static int getNuSockets() 
{	return NuSockets;	}

private static void setNuSockets(int nuSockets) 
{	NuSockets = nuSockets;	}

public static int getNuCores() 
{	return NuCores;		}

private static void setNuCores(int nuCores) 
{	NuCores = nuCores;	}

public static int getNuPUs() 
{	return NuPUs;		}

private void setNuPUs(int nuPUs) 
{	NuPUs = nuPUs;		}

public static String getHwloc_info() 
{	return hwloc_info;	}

private void setHwloc_info(String hwloc_info) 
{	TestingSystem.hwloc_info = hwloc_info;		}

public String getLstopo_physical() 
{	return lstopo_physical;		}

public static void setLstopo_physical(String lstopo_physical) 
{	TestingSystem.lstopo_physical = lstopo_physical;	}

public String getNumactl_hardware() 
{	return numactl_hardware;	}

public static void setNumactl_hardware(String numactl_hardware) 
{	TestingSystem.numactl_hardware = numactl_hardware;	}

public void GetCPUConfiguration()
{
    	String[] hwlock = "hwloc-info".split("\\s+");
    	String[] lstopo = "lstopo --physical -".split("\\s+");
    	String[] numactl = "numactl --hardware".split("\\s+");
    	
	setHwloc_info(FileOutput.RunCommand( true, hwlock ));
	setLstopo_physical(FileOutput.RunCommand( true, lstopo ));
	setNumactl_hardware(FileOutput.RunCommand( true, numactl ));

	setNuSockets(GetNumbersOfUnit("Socket"));
	setNuPUs(GetNumbersOfUnit("PU"));
	setNuCores(GetNumbersOfUnit("Core"));
	setNuNumas(GetNumbersOfUnit("NUMA"));
}

public static int GetNumbersOfUnit(String SearchingText)
{
	String regExp = "(\\d+)\\s+"; 
	
	Pattern pattern = Pattern.compile(regExp + SearchingText);
	Matcher matcher = pattern.matcher(getHwloc_info());

	int NumberOfUnit = 0;
	
	while (matcher.find()) 
	{	NumberOfUnit = Integer.parseInt(matcher.group(1));	}

	return NumberOfUnit;
}

public static void GetRHELVersion()
{		
	Pattern pattern = Pattern.compile("(.*)\\.(el\\d+|fc\\d+)\\.(.*)");
	String[] CommandArgs = "uname -r".split("\\s+");
	
	Matcher matcher = pattern.matcher( FileOutput.RunCommand( false, CommandArgs ));

	while (matcher.find())
	{	setKernelVersion(matcher.group(1));
		setRHVersion(matcher.group(2));
		setMachineID(matcher.group(3));		}
}

public static List<Float> GetProcessorsUsage( BufferedWriter bw ) throws Exception
{
	List<Float> ProcessorsUsage = new ArrayList<>();
	
	String[] command = "mpstat -P ALL 1 1 | grep Average | grep -v CPU".split("\\s+"); 
	Pattern pattern = Pattern.compile("\\s+(\\d+)$");
	
	RThreads RT = new RThreads( true, command );
	
	while ( !RT.isFinished() )
	{	Thread.sleep( 500 );	}
	
	Matcher matcher = pattern.matcher( RT.getOutputString() );
	
	boolean firstLine = true;
	
	while (matcher.find())
	{	Float UsageFloat = 100f - Float.parseFloat( matcher.group(1));
		ProcessorsUsage.add( UsageFloat ) ;	
		
		if ( !firstLine )
		{	bw.write(" ");
	    		firstLine = false;	}
		
		bw.write( UsageFloat.toString() );
		bw.flush();
	}
	
	bw.newLine();
	bw.close();
	
	return ProcessorsUsage;	
}

public static void printHWreport()
{	FileOutput.AppendToStandardOutput(hwloc_info);
	FileOutput.AppendToStandardOutput(lstopo_physical);
	FileOutput.AppendToStandardOutput(numactl_hardware);	}


}
